package com.ywu.standard.gateway.handler.user;

import com.ywu.boot.config.BootConfigAppConfig;
import com.ywu.boot.context.YwuContext;
import com.ywu.boot.context.YwuContextHolder;
import com.ywu.boot.context.YwuContextTenant;
import com.ywu.common.constant.CommonConstant;
import com.ywu.common.gson.GsonUtils;
import com.ywu.common.mapper.YwuBeanMapper;
import com.ywu.common.result.CommonResult;
import com.ywu.common.utils.AesUtils;
import com.ywu.standard.gateway.handler.user.impl.UserHandlerInterface;
import com.ywu.tenant.spi.dto.TenantDto;
import com.ywu.tenant.spi.entity.TenantEntity;
import com.ywu.tenant.spi.spi.TenantSpi;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;

import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName UserTenantHandler
 * @Description TODO
 * @Author GroundDemo
 * @Date 2024/5/26 12:58
 * @Version 1.0
 **/
@Component
@Slf4j
@Order(4)
public class UserTenantHandler implements UserHandlerInterface {
    private static final String TENANT_INFO_HEADER_KEY = "X-Pix-Ywu-Tenant-Info";

    private static final String GUEST_ACCOUNT = "guest";

    private static final String YWU_GATEWAY_TENANT_REDIS_KEY = "YWU_GATEWAY_TENANT:gateway:";

    @Autowired
    private TenantSpi tenantSpi;

    @Autowired
    private BootConfigAppConfig bootConfigAppConfig;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    public Object handle(ServerWebExchange exchange) {
        log.debug("UserTenantHandler begin");
        // 从上下文中获取租户ID
        YwuContext currentContext = YwuContextHolder.getCurrentContext();
        String tenantId = currentContext.getYwuContextTenant().getTenantId();
        if (StringUtils.isBlank(tenantId)) {
            return exchange;
        }
        TenantEntity data = null;
        // 优先查询缓存
        String redisInfo = redisTemplate.opsForValue().get(YWU_GATEWAY_TENANT_REDIS_KEY + tenantId);
        if (Objects.nonNull(redisInfo)) {
            log.debug("gateway query tenant info using redis cache");
            data = GsonUtils.deserialize(redisInfo, TenantEntity.class);
        } else {
            // 根据租户ID查询租户详情
            TenantDto tenantDto = new TenantDto();
            tenantDto.setTenantId(tenantId);
            CompletableFuture<CommonResult<TenantEntity>> resultCompletableFuture =
                    CompletableFuture.supplyAsync(() -> tenantSpi.queryTenantInfoByTenantId(tenantDto));
            CommonResult<TenantEntity> listCommonResult;
            try {
                listCommonResult = resultCompletableFuture.get();
            } catch (InterruptedException | ExecutionException e) {
                log.error("UserTenantHandler CompletableFuture spi query error {}", e.getMessage());
                return CommonResult.error().setCode(CommonConstant.USER_TENANT_QUERY_INFO_ERROR).setErrorCode(CommonConstant.USER_TENANT_QUERY_INFO_ERROR_MESSAGE)
                        .setMessage("租户查询异常!");
            }
            if (!StringUtils.equals(listCommonResult.getCode(), "200")) {
                return CommonResult.error().setCode(CommonConstant.USER_TENANT_QUERY_INFO_ERROR)
                        .setErrorCode(CommonConstant.USER_TENANT_QUERY_INFO_ERROR_MESSAGE)
                        .setMessage("租户ID不存在");
            }
            data = listCommonResult.getData();
            // 添加缓存
            redisTemplate.opsForValue().set(YWU_GATEWAY_TENANT_REDIS_KEY + tenantId, GsonUtils.serialize(data));
            redisTemplate.expire(YWU_GATEWAY_TENANT_REDIS_KEY + tenantId, 1, TimeUnit.HOURS);
        }
        YwuContextTenant ywuContextTenant = YwuBeanMapper.map(data, YwuContextTenant.class);
        currentContext.setYwuContextTenant(ywuContextTenant);
        // 加密数据存入请求头中
        String ywuContextTenantInfo = GsonUtils.serialize(ywuContextTenant);
        String encryptYwuContextTenantInfo;
        try {
            encryptYwuContextTenantInfo = AesUtils.encrypt(ywuContextTenantInfo, bootConfigAppConfig.getSecretKey());
        } catch (Exception e) {
            log.error("UserTenantHandler ywuContextTenantInfo encrypt error {}", e.getMessage());
            return CommonResult.error().setCode(CommonConstant.USER_TENANT_QUERY_INFO_ERROR).setErrorCode(CommonConstant.USER_TENANT_QUERY_INFO_ERROR_MESSAGE)
                    .setMessage("租户信息加密异常!");
        }
        ServerHttpRequest mutatedUserRoleRequest = exchange.getRequest().mutate().header(TENANT_INFO_HEADER_KEY, encryptYwuContextTenantInfo).build();
        return exchange.mutate().request(mutatedUserRoleRequest).build();
    }
}
